package sunsun.xiaoli.jiarebang.utils.audiorecord;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.text.TextUtils;
import android.util.Log;

import com.itboye.pondteam.utils.LogUtils;
import com.itboye.pondteam.utils.loadingutil.MAlert;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import static sunsun.xiaoli.jiarebang.utils.audiorecord.FileUtils.deleteDirectory;

/**
 * Created by HXL on 16/8/11.
 * 用于实现录音   暂停录音
 */
public class AudioRecorder {
    private static AudioRecorder audioRecorder;
    //音频输入-麦克风
    private final static int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;
    //采用频率
    //44100是目前的标准，但是某些设备仍然支持22050，16000，11025
    //采样频率一般共分为22.05KHz、44.1KHz、48KHz三个等级
    private final static int AUDIO_SAMPLE_RATE = 16 * 1000;
    //声道 单声道
    private final static int AUDIO_CHANNEL = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    //编码
    private final static int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
    // 缓冲区字节大小
    private int bufferSizeInBytes = 0;

    //录音对象
    private AudioRecord audioRecord;

    //录音状态
    private Status status = Status.STATUS_NO_READY;

    //文件名
    private String fileName;

    //录音文件
//    private List<String> filesName = new ArrayList<>();
    private Activity activity;
    private AudioRecorderListener audioRecorderListener;
    private boolean isRecording;
    private File file;
    private DecibelLisenter decibelLisenter;

    private AudioRecorder() {
    }

    //单例模式
    public static AudioRecorder getInstance() {
        if (audioRecorder == null) {
            audioRecorder = new AudioRecorder();
        }
        return audioRecorder;

    }

    /**
     * 创建录音对象
     */
    public void createAudio(String fileName, int audioSource, int sampleRateInHz, int channelConfig, int audioFormat) {
        // 获得缓冲区字节大小
        bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
                channelConfig, channelConfig);
        audioRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes);
        this.fileName = fileName;
    }

    FileOutputStream fos = null;
    int readsize = 0;

    /**
     * 创建默认的录音对象
     *
     * @param fileName 文件名
     */
    public void createDefaultAudio(String fileName) {
        // 获得缓冲区字节大小
        bufferSizeInBytes = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE,
                AUDIO_CHANNEL, AUDIO_ENCODING);
        audioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING, bufferSizeInBytes);
        this.fileName = fileName;
        status = Status.STATUS_READY;
        audiodata = new byte[bufferSizeInBytes];
        deleteDirectory("");//先清空里面所有文件 /g726En/
        try {
            String currentFileName = fileName;
//            if (status == Status.STATUS_PAUSE) {
//                //假如是暂停录音 将文件名后面加个数字,防止重名文件内容被覆盖
//                currentFileName += filesName.size();
//
//            }
//            filesName.add(currentFileName);
            file = new File(FileUtils.getPcmFileAbsolutePath(currentFileName));
            if (file.exists()) {
                file.delete();
            }
            fos = new FileOutputStream(file);// 建立一个可存取字节的文件
        } catch (IllegalStateException e) {
            Log.e("AudioRecorder", e.getMessage());
            throw new IllegalStateException(e.getMessage());
        } catch (FileNotFoundException e) {
            Log.e("AudioRecorder", e.getMessage());

        }

    }


    /**
     * 开始录音
     *
     * @param listener 音频流的监听
     */
    public void startRecord(final RecordStreamListener listener) {

        if (status == Status.STATUS_NO_READY || TextUtils.isEmpty(fileName)) {
            MAlert.alert("录音尚未初始化,请检查是否禁止了录音权限~");
        }
        if (status == Status.STATUS_START) {
            MAlert.alert("正在录音");
        } else if (status == Status.STATUS_PAUSE) {
            status = Status.STATUS_START;
        } else if (status == Status.STATUS_READY) {
            audioRecord.startRecording();
        }

        new Thread(() -> writeDataTOFile(listener)).start();
        LogUtils.v("AudioRecorder", "===startRecord===" + audioRecord.getState());
//        new Thread(() -> StartRecord2()).start();
    }

    /**
     * 暂停录音
     */
    public void pauseRecord() {
        LogUtils.v("AudioRecorder", "===pauseRecord===");
        if (status != Status.STATUS_START) {
            MAlert.alert("没有在录音");
        } else {
//            audioRecord.stop();
            status = Status.STATUS_PAUSE;
        }
    }

    /**
     * 停止录音
     */
    public void stopRecord() {
        LogUtils.v("AudioRecorder", "===stopRecord===");
        if (status == Status.STATUS_NO_READY || status == Status.STATUS_READY) {
            MAlert.alert("录音尚未开始");
        } else {
            audioRecord.stop();
            status = Status.STATUS_STOP;
            release();
        }
    }


    /**
     * 停止录音
     */
    public void stopRecord(String fileName, AudioRecorderListener audioRecorderListener) {
        this.fileName = fileName;
        this.audioRecorderListener = audioRecorderListener;
        LogUtils.v("AudioRecorder", "===stopRecord===");
        if (status == Status.STATUS_NO_READY || status == Status.STATUS_READY) {
            MAlert.alert("录音尚未开始");
        } else {
            audioRecord.stop();
            status = Status.STATUS_STOP;
            release();
        }
    }

    /**
     * 释放资源
     */
    public void release() {
        LogUtils.v("AudioRecorder", "===release===");
        //假如有暂停录音
        try {
            String path = FileUtils.getPcmFileAbsolutePathForFinal(fileName);
            boolean re = file.renameTo(new File(path));
            if (re) {
                String wavPath = FileUtils.getWavFileAbsolutePath(fileName, false);
                boolean wavRe = PcmToWav.makePCMFileToWAVFile(path, wavPath, false);
                if (wavRe) {
                    audioRecorderListener.success("保存成功", path, fileName);
                    Log.e("AudioRecorder", "success");
                } else {
                    //操作失败
                    Log.e("AudioRecorder", "mergePCMFilesToWAVFile fail");
                    audioRecorderListener.fail("mergePCMFilesToWAVFile fail");
                }
            }

//            if (filesName.size() > 0) {
//                List<String> filePaths = new ArrayList<>();
//                for (String fileName : filesName) {
//                    filePaths.add(FileUtils.getPcmFileAbsolutePath(fileName));
//                }
//                //清除
//                filesName.clear();
//                //将多个pcm文件转化为wav文件
////                mergePCMFilesToWAVFile(filePaths);
//                //合并pcm文件
//                mergePCMFILes(filePaths);
//            } else {
//                //这里由于只要录音过filesName.size都会大于0,没录音时fileName为null
//                //会报空指针 NullPointerException
//                // 将单个pcm文件转化为wav文件
//                //LogUtils.v("AudioRecorder", "=====makePCMFileToWAVFile======");
//                //makePCMFileToWAVFile();
//            }
        } catch (IllegalStateException e) {
            throw new IllegalStateException(e.getMessage());
        }
        try {
            if (fos != null) {
                fos.close();// 关闭写入流
            }
        } catch (IOException e) {
            Log.e("AudioRecorder", e.getMessage());
        }
        if (audioRecord != null) {
            audioRecord.release();
            audioRecord = null;
        }

        status = Status.STATUS_NO_READY;
    }

//    private void mergePCMFILes(List<String> filePaths) {
//        int lenth = 0;
//        List<byte[]> byteList = new ArrayList<>();
//        for (String filePath : filePaths) {
//            byte[] bytes = readFile(new File(filePath));
//            byteList.add(bytes);
//            lenth += bytes.length;
//        }
//        byte[] byteTotal = new byte[lenth];
//        for (int i = 0; i < byteList.size(); i++) {
//            byte[] bytes = byteList.get(i);
//            for (int i1 = 0; i1 < bytes.length; i1++) {
//                byteTotal[i * i1] = bytes[i1];
//            }
//        }
//
//        String path = FileUtils.getPcmFileAbsolutePathForFinal(fileName);
//        //写进文件
//
//        if (addFile(byteTotal, path, filePaths)) {
//            audioRecorderListener.success("保存成功", path);
//            Log.e("AudioRecorder", "success");
//        } else {
//            //操作失败
//            Log.e("AudioRecorder", "mergePCMFilesToWAVFile fail");
//            audioRecorderListener.fail("mergePCMFilesToWAVFile fail");
//        }
//
//    }

    /**
     * 将pcm合并成wav
     *
     * @param filePaths
     */
//    private void mergePCMFilesToWAVFile(final List<String> filePaths) {
//        new Thread(() -> {
//            String path = FileUtils.getWavFileAbsolutePath(fileName);
//            if (PcmToWav.mergePCMFilesToWAVFile(filePaths, path)) {
//                //操作成功
//                audioRecorderListener.success("保存成功", path);
//                Log.e("AudioRecorder", "success");
//            } else {
//                //操作失败
//                Log.e("AudioRecorder", "mergePCMFilesToWAVFile fail");
//                audioRecorderListener.fail("mergePCMFilesToWAVFile fail");
//            }
//            fileName = null;
//        }).start();
//    }

    /**
     * 取消录音
     */
    public void canel() {
//        filesName.clear();
        fileName = null;
        if (audioRecord != null) {
            audioRecord.release();
            audioRecord = null;
        }

        status = Status.STATUS_NO_READY;
    }

    /**
     * 将音频信息写入文件
     *
     * @param listener 音频流的监听
     */
    byte[] audiodata = new byte[bufferSizeInBytes];

    private void writeDataTOFile(RecordStreamListener listener) {

        // new一个byte数组用来存一些字节数据，大小为缓冲区大小
        //将录音状态设置成正在录音状态
        status = Status.STATUS_START;
        System.out.println("正在写入中外层" + status);
        while (status == Status.STATUS_START) {
            System.out.println("正在写入中");
            readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);
            double value = calculateVolume(audiodata);
            if (this.decibelLisenter != null) {
                this.decibelLisenter.getDecibleValue(value);
            }
            if (AudioRecord.ERROR_INVALID_OPERATION != readsize && fos != null) {
                try {
                    LogUtils.v("AudioRecorder", "写入中" + audiodata.length);
                    fos.write(audiodata);
//                    countDb(audiodata);
                    if (listener != null) {
                        //用于拓展业务
                        listener.recordOfByte(audiodata, 0, audiodata.length);
                    }
                } catch (IOException e) {
                    Log.e("AudioRecorder", e.getMessage());
                }
            }
        }

    }

    private double calculateVolume(byte[] buffer) {
        double sumVolume = 0.0;

        double avgVolume = 0.0;

        double volume = 0.0;

        for (int i = 0; i < buffer.length; i += 2) {

            int v1 = buffer[i] & 0xFF;

            int v2 = buffer[i + 1] & 0xFF;

            int temp = v1 + (v2 << 8);// 小端

            if (temp >= 0x8000) {

                temp = 0xffff - temp;

            }

            sumVolume += Math.abs(temp);

        }

        avgVolume = sumVolume / buffer.length / 2;

        volume = Math.log10(1 + avgVolume) * 10;
        return volume;

    }

    private void whiteByte() {

    }


    /**
     * 将单个pcm文件转化为wav文件
     */
    private void makePCMFileToWAVFile() {
        new Thread(() -> {
            if (PcmToWav.makePCMFileToWAVFile(FileUtils.getPcmFileAbsolutePath(fileName), FileUtils.getWavFileAbsolutePath(fileName), true)) {
                //操作成功
            } else {
                //操作失败
                Log.e("AudioRecorder", "makePCMFileToWAVFile fail");
                throw new IllegalStateException("makePCMFileToWAVFile fail");
            }
            fileName = null;
        }).start();
    }

    /**
     * 获取录音对象的状态
     *
     * @return
     */
    public Status getStatus() {
        return status;
    }

    /**
     * 获取本次录音文件的个数
     *
     * @return
     */
//    public int getPcmFilesCount() {
//        return filesName.size();
//    }
    public void setActivity(Activity mainActivity) {
        this.activity = mainActivity;
    }

    public void setDecibelLisenter(DecibelLisenter decibelLisenter) {
        this.decibelLisenter = decibelLisenter;
    }

    public DecibelLisenter getDecibelLisenter() {
        return decibelLisenter;
    }

    /**
     * 录音对象的状态
     */
    public enum Status {
        //未开始
        STATUS_NO_READY,
        //预备
        STATUS_READY,
        //录音
        STATUS_START,
        //暂停
        STATUS_PAUSE,
        //停止
        STATUS_STOP
    }

    public interface DecibelLisenter {
        int getDecibleValue(double value);
    }

}
